	/*
 * Created on Jun 8, 2004
 */
package com.stottlerhenke.simbionic.engine.core;

import java.util.*;

import com.stottlerhenke.simbionic.api.*;
import com.stottlerhenke.simbionic.common.*;
import com.stottlerhenke.simbionic.engine.file.SB_StreamReader;
import com.stottlerhenke.simbionic.engine.SB_SingletonBook;

/**
 *
 * 
 * This class forms a compound node - a list of action and behavior nodes that
 * are all executed in a single tick.
 */
public class SB_CompoundNode extends SB_Node
{
	/**
	 * @param owner
	 * @param nodeID
	 */
	public SB_CompoundNode(SB_BehaviorElement owner, int nodeID)
	{
		super(owner, nodeID);
		_nodes = new Vector();
	}

	/**
	 * @see com.stottlerhenke.simbionic.engine.core.SB_Node#GetNodeType()
	 */
	public ENodeType GetNodeType()
	{
		return ENodeType.kCompoundNode;
	}

	/**
	 * Reads a compound node from the specification.
	 * 
	 * @param reader
	 */
	public void load(SB_StreamReader reader, SB_SingletonBook book)
			throws SB_FileException
	{
		super.load(reader, book); 
		
		int numSubNodes = reader.readInt();
		for (int x = 0; x < numSubNodes; x++)
		{
			_nodes.add(SB_Node.readNode(reader, book, this));
		}
	}

	/**
	 * Override the default implementation. Initialize this node and all subnodes
	 */
	public void initialize(ArrayList transitions,SB_SingletonBook book)
	throws SB_Exception
	{
		super.initialize(transitions, book);
		
		for (int i = 0; i < _nodes.size(); i++)
	  {
			((SB_Node)_nodes.get(i)).initialize(transitions,book);
	  }		
	}
	/** 
	 * Each time this is called, execute another action
	 * 
	 */
	public void Execute(SB_Entity entity, SB_ExecutionFrame contextFrame,
			SB_SingletonBook book) throws SB_Exception
	{
		int nodeIndex;
		if (!contextFrame.HasNodeBeenInvoked())
		{
			contextFrame.SetNodeBeenInvoked(true);
			nodeIndex = 0;
		} 
		else
		{
			nodeIndex = contextFrame.GetNodeInvocationCount();
			contextFrame.SetNodeBeenInvoked(nodeIndex + 1);
		}
		
		if (nodeIndex < _nodes.size())
		{
			contextFrame.SetNodeBeenInvoked(false); //Actions require this for the current frame
			SB_Node tempNode = ((SB_Node) _nodes.get(nodeIndex));
			tempNode.Execute(entity, contextFrame, book);
			contextFrame.SetNodeBeenInvoked(nodeIndex + 1); //Set back to the correct value afterwords
			
			//Compound nodes are one-tick, so tell the entity to keep going
			//SB_EntityData state = entity.GetState();
			//state.SetDoAnotherTick(true);
		}
		else
		if(nodeIndex >= _nodes.size() ) //First time after all executed
		{
		  contextFrame.checkExitCompoundNode();
		  
		  if (SIM_Constants.DEBUG_INFO_ON)
			  book.getLogger().log( "[" + entity.toString() + "] MSG: Completed compound node, execution mode set to: " + entity.GetState().GetExecStack().getStatusString(),SB_Logger.TICK);

		}
	}

	/**
	 * @return The number of times Execute needs to be called for this node
	 *         (default is once)
	 */
	public int GetExecutionCount()
	{
		return _nodes.size() + 1; //We need to execute this one extra time to remove OT/NI
	}

	Vector _nodes;
}